#ifndef clox_byte_code_h
#define clox_byte_code_h

#include "vector.h"

typedef struct Obj Obj;

typedef enum {
    OP_RETURN,
    OP_CONSTANT,
    OP_NEGATE,
    OP_ADD,
    OP_SUBSTRACT,
    OP_MULTIPLY,
    OP_DIVIDE,
    OP_VARIABLE_DECLARE,
    OP_ASSIGNMENT,
    OP_VARIABLE_GET,
    OP_PRINT,
    OP_POP,
    OP_NIL,
    OP_LOCAL_GET,
    OP_LOCAL_ASSIGN,
    OP_JMP_IF_FALSE,
    OP_JMP_IF_TRUE,
    OP_JMP,
    OP_LOOP,
    OP_LESS,
    OP_GREATER,
    OP_EQUAL,
    OP_NOT,
    OP_CALL
} OpCode;

typedef struct {
    OpCode code;
    int line;
} Code;

typedef enum {
    VAL_NULL,
    VAL_NUMBER,
    VAL_STRING,
    VAL_FUNCTION
} ValueType;

typedef struct {
    ValueType type;
    union
    {
        double num;
        Obj* obj;
    } val;
} Value;

typedef struct Chunk
{
    Vector codes;
    Vector constants;
} Chunk;

void chunkInit(Chunk *chunk);
void chunkPrint(Chunk *chunk);
void chunkAddCode(Chunk *chunk, OpCode opCode, int line);
void chunkUpdateCode(Chunk *chunk, OpCode opCode, int idx);
int chunkAddConstant(Chunk *chunk, Value val);
Code chunkGetCode(Chunk *chunk, int idx);
Value chunkGetConstant(Chunk *chunk, int idx);
double chunkVal2num(Value val);
Value chunkNum2Val(double num);
void valuePrint(Value* val);

#endif
